//READ: set the addr_r_i and addr_r_valid_i right values  before the data_r_valid_o == 1
//WRITE: set addr_w_valid_i,addr_w_i,data_w_i,data_w_mask_i,data_w_valid_i,
//right values before data_w_end == 1;
`define WAIT_ADDR 1'b0
`define WAIT_DATA 1'b1
module MODULE_AXI_Lite_M
#(AWIDTH = 32,
	DWIDTH = 64,
	MASKLEN = 8
)
(
	input 								clk_i,
	input									rst_i,
	
	input									addr_r_valid_i, //this valid main the addr_r_i is valid
	input		[AWIDTH-1:0]	addr_r_i,
	output	[DWIDTH-1:0]	data_r_o,
	output								data_r_valid_o,
	
	input									addr_w_valid_i, //this valid main the addr_w_i is valid
	input		[AWIDTH-1:0]	addr_w_i,
	input		[DWIDTH-1:0]	data_w_i,
	input		[MASKLEN-1:0] data_w_mask_i,
	input									data_w_valid_i,
	output								data_w_end_o,
	input		[2:0]					axi_size_i,
	//AXI4_Lite 
	output	[AWIDTH-1:0]	araddr_o,
	output								arvalid_o,
	input									arready_i,//

	input		[DWIDTH-1:0]	rdata_i,
	input		[1:0]					rresp_i,//
	input									rvalid_i,//
	output								rready_o,
	
	output	[AWIDTH-1:0]	awaddr_o,
	output								awvalid_o,
	input									awready_i,

	output	[DWIDTH-1:0]	wdata_o,
	output	[MASKLEN-1:0]	wstrb_o,
	output								wvalid_o,
	input									wready_i,

	input		[1:0]					bresp_i,//not finished 
	input									bvalid_i,//not...
	output								bready_o,//not...

	output								wlast_o,	
	output	[2:0]					awsize_o,
	output	[2:0]					arsize_o
);
assign bready_o = 1'b1;
assign awsize_o[2:0] = axi_size_i;
assign arsize_o[2:0] = axi_size_i;
/////////////////////////////////state machine read start///////////////////////////
//Analyse
wire r_state_now;
wire r_state_next;
//reg for state
Reg #(1,0)	r_state (clk_i,rst_i,r_state_next,r_state_now,1);
// choose the next state
MuxKeyWithDefault #(2,1,1) mux_r_state_next(.out(r_state_next),.key(r_state_now),.default_out(0),.lut({
	`WAIT_ADDR,	arready_i & arvalid_o ? `WAIT_DATA : `WAIT_ADDR,
	`WAIT_DATA, rvalid_i & rready_o ? `WAIT_ADDR :	`WAIT_DATA
}));
//send the read_addr, and save the arvalid and araddr if arvalid_o & !arready_i
assign araddr_o[AWIDTH-1:0] = addr_r_i[AWIDTH-1:0];
assign arvalid_o = ~r_state_now & (~rst_i) &addr_r_valid_i;//&(!data_valid_o);
assign rready_o = r_state_now& (~rst_i);

//reg for read data and valid
wire write_data_reg_en;
assign write_data_reg_en = (r_state_now == `WAIT_DATA)&rready_o&rvalid_i;
Reg #(DWIDTH,0) data (clk_i,rst_i,rdata_i[DWIDTH-1:0],data_r_o[DWIDTH-1:0],write_data_reg_en);
//assign data_valid_o = write_data_reg_en;
Reg #(1,0)	data_valid(clk_i,rst_i,write_data_reg_en,data_r_valid_o,1);
/////////////////////////////////state machine read end//////////////////////////////


/////////////////////////////////state machine write start///////////////////////////
wire w_state_now;
wire w_state_next;
//reg for state
Reg #(1,0)	w_state (clk_i,rst_i,w_state_next,w_state_now,1);
// choose the next state
MuxKeyWithDefault #(2,1,1) mux_w_state_next(.out(w_state_next),.key(w_state_now),.default_out(0),.lut({
	`WAIT_ADDR,	awready_i & awvalid_o? `WAIT_DATA : `WAIT_ADDR,
	`WAIT_DATA, wvalid_o & wready_i ? `WAIT_ADDR :	`WAIT_DATA
}));
//decide signals according to the state
assign awaddr_o[AWIDTH-1:0] = addr_w_i[AWIDTH-1:0];
assign awvalid_o = ~w_state_now & (~rst_i) &addr_w_valid_i;//&(!data_valid_o);

assign wdata_o[DWIDTH-1:0] = data_w_i[DWIDTH-1:0];
assign wstrb_o[MASKLEN-1:0] = data_w_mask_i[MASKLEN-1:0];
assign wvalid_o = w_state_now & (~rst_i)& data_w_valid_i ;
assign data_w_end_o = (w_state_now == `WAIT_DATA) &wvalid_o & wready_i;
assign wlast_o = data_w_end_o;
/////////////////////////////////state machine write end//////////////////////////////


endmodule
